package com.artnology.independence.views.operations;

import java.util.Collection;
import java.util.HashSet;

import org.apache.commons.collections15.Predicate;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.AbstractOperation;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

import com.artnology.independence.model.DVNode;
import com.artnology.independence.model.DependencyGraph;
import com.artnology.independence.model.relationships.DVReference;

import edu.uci.ics.jung.algorithms.filters.VertexPredicateFilter;
import edu.uci.ics.jung.graph.util.EdgeType;

public class RemoveNodeFromGraphOperation extends AbstractOperation {
	
	DependencyGraph depGraph = null;
	Collection<DVNode> nodesToFilter = null;
	Collection<DVReference> rememberFilteredEdges = new HashSet<DVReference>();
	Collection<DVNode> rememberFilteredVertices = new HashSet<DVNode>();

	public RemoveNodeFromGraphOperation(String label,
			DependencyGraph depGraph, Collection<DVNode> nodesToFilter) {
		super(label);
		this.nodesToFilter = nodesToFilter;
		this.depGraph = depGraph;
	}

	@Override
	public IStatus execute(IProgressMonitor arg0, IAdaptable arg1)
			throws ExecutionException {
		for (DVNode node : nodesToFilter) {
			if (depGraph.getGraph().containsVertex(node)) {
				rememberFilteredEdges.addAll(depGraph.getGraph().getIncidentEdges(node));
			}
		}
		VertexPredicateFilter<DVNode, DVReference> filter = new VertexPredicateFilter<DVNode, DVReference>(new Predicate<DVNode>() {
			@Override
			public boolean evaluate(DVNode node) {
				boolean filterNode = nodesToFilter.contains(node);
				if (filterNode) {
					rememberFilteredVertices.add(node);
				}
				return !filterNode;
			}
		});
		depGraph.setGraph(filter.transform(depGraph.getGraph()));
		return Status.OK_STATUS;
	}

	@Override
	public IStatus redo(IProgressMonitor arg0, IAdaptable arg1)
			throws ExecutionException {	
		return execute(arg0, arg1);
	}

	@Override
	public IStatus undo(IProgressMonitor arg0, IAdaptable arg1)
			throws ExecutionException {
		for (DVNode node : rememberFilteredVertices) {
			depGraph.getGraph().addVertex(node);
		}
		
		for (DVReference ref : rememberFilteredEdges) {
			depGraph.getGraph().addEdge(ref, ref.getReferenceFromNode(), ref.getReferencedNode(), EdgeType.DIRECTED);
		}
		rememberFilteredEdges.clear();
		rememberFilteredVertices.clear();
		depGraph.setGraph(depGraph.getGraph());
		return Status.OK_STATUS;
	}

}
